﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework;
using RPGXEngine.Graphics;

namespace RPGXEngine.Object
{
    public class GameMesh
    {
        #region Properties

        public float X
        {
            get { return _x; }
            set { _x = value; }
        }
        private float _x = 0.0f;

        public float Z
        {
            get { return _z; }
            set { _z = value; }
        }
        private float _z = 0.0f;

        public float Scale
        {
            get { return _scale; }
            set { _scale = value; }
        }
        private float _scale = 0.0f;

        public Vector3 Position
        {
            get { return _position; }
            set { _position = value; }
        }
        private Vector3 _position = new Vector3();

        public string FileName
        {
            get { return _fileName; }
            set { _fileName = value; }
        }
        private string _fileName = String.Empty;

        public GameMeshModel RenderModel
        {
            get { return _renderModel; }
            set { _renderModel = value; }
        }
        private GameMeshModel _renderModel = null;

        public Matrix WorldMatrix
        {
            get
            {
                return Matrix.CreateScale(this.Scale) * Matrix.CreateTranslation(this.Position);
            }
        }

        #endregion

        #region Public Methods

        public GameMesh()
        {
        }

        public bool FromXML(XElement element)
        {
            this.X = (float)Convert.ToDouble(element.Attribute("x").Value);
            this.Z = (float)Convert.ToDouble(element.Attribute("z").Value);
            this.Scale = (float)Convert.ToDouble(element.Attribute("scale").Value);
            this.FileName = Convert.ToString(element.Attribute("filename").Value);

            return true;
        }

        public void Load(ContentManager content, Effect effect)
        {
            this.RenderModel = ModelPool.Add(this.FileName, content);

            foreach (ModelMesh modelMesh in this.RenderModel.Model.Meshes)
            {
                foreach (ModelMeshPart part in modelMesh.MeshParts)
                {
                    part.Effect = effect.Clone();
                }
            }

            this.Position = new Vector3(this.X, 0.0f, this.Z);
        }

        public void Render(Matrix world, Camera camera, string technique)
        {
            int textureIndex = 0;

            Matrix[] bones = new Matrix[this.RenderModel.Model.Bones.Count];
            this.RenderModel.Model.CopyAbsoluteBoneTransformsTo(bones);

            world = world * this.WorldMatrix;

            foreach (ModelMesh modelMesh in this.RenderModel.Model.Meshes)
            {
                Matrix bone = bones[modelMesh.ParentBone.Index];

                Matrix boneWorld = bone * world;

                foreach (Effect fx in modelMesh.Effects)
                {
                    fx.CurrentTechnique = fx.Techniques[technique];
                    fx.Parameters["xProjection"].SetValue(camera.Projection);
                    fx.Parameters["xView"].SetValue(camera.View);
                    fx.Parameters["xWorld"].SetValue(boneWorld);
                    fx.Parameters["xTexture"].SetValue(this.RenderModel.Textures[textureIndex]);
                }

                modelMesh.Draw();
            }
        }

        #endregion
    }
}
